package my.test.csdn.weixin_43767015.basic.ch12.transaction.declarative.annotation.propagation.required.eachcall.service;

import javax.annotation.Resource;

import org.springframework.aop.framework.AopContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import my.test.bean.ex14.synchronization.TransactionManageService;
import my.test.csdn.weixin_43767015.basic.ch12.transaction.declarative.annotation.synchronization.TransactionalMessageSender;

@Component
public class TxRequiredEachService {
    /**
     * jdbc模版，用于操作数据库
     */
    @Resource
    private JdbcTemplate jdbcTemplate;
	
    
    /** m1中调用m2 */
	@Transactional(propagation = Propagation.REQUIRED)
    public void m1() {
        String sql = "insert into tx_study (name,age) values (?,?)";
        jdbcTemplate.update(sql, "TxRequired_m1", 30);
		//注册事务提交后的操作  
		TransactionManageService.afterCommit(() -> System.out.println("Transaction committed successfully!"));
		//注册事务回滚后的操作
		TransactionManageService.afterRollback(() -> System.out.println("Transaction rolledback!"));	
		TransactionSynchronizationManager.registerSynchronization(new TransactionalMessageSender());
		TxRequiredEachService o =(TxRequiredEachService)AopContext.currentProxy();
        o.m2();
        //抛出一个RuntimeException
        throw new RuntimeException();
    }

	@Transactional(propagation = Propagation.REQUIRED)
	public void m2() {
        String sql = "insert into tx_study (name,age) values (?,?)";
        jdbcTemplate.update(sql, "TxRequired_m2", 30);        
        //抛出一个RuntimeException
        //throw new RuntimeException();
	}
	
	/** m2不会再开启事务，而是加入到m1开启的事务中去 */
    @Resource
    private DataSourceTransactionManager transactionManager;
	
    public DataSourceTransactionManager getTransactionManager() {
    	return transactionManager;
    }
    
    public void tran() {
        //获得一个事务管理器
        DataSourceTransactionManager txManager = getTransactionManager();
    	//创建一个事务定义对象，可以设置事务的属性
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        //只能以编程方式执行时才能显式设置事务名称
        def.setName("SomeTxName");
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        //m1开启一个新事务
        TransactionStatus status = txManager.getTransaction(def);
        try {
        	//执行m1方法业务逻辑，m1内部还调用m2方法，m2不再开启新事务
            m1();
        } catch (Exception ex) {
            //回滚
            txManager.rollback(status);
            throw ex;
        }
        //提交
        txManager.commit(status);
    }	
}
